package com.zy.swagger.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zy.swagger.base.BaseDao;
import com.zy.swagger.base.BaseServiceImpl;
import com.zy.swagger.constant.ProjectConstant;
import com.zy.swagger.converter.InterfaceManageConverter;
import com.zy.swagger.dao.AppManageDao;
import com.zy.swagger.dao.InterfaceManageDao;
import com.zy.swagger.dao.RequestRecordDao;
import com.zy.swagger.dao.SysUserDao;
import com.zy.swagger.dto.CommonIdDTO;
import com.zy.swagger.dto.InterfaceManageDTO;
import com.zy.swagger.entity.AppManage;
import com.zy.swagger.entity.InterfaceManage;
import com.zy.swagger.entity.RequestRecord;
import com.zy.swagger.exception.BaseException;
import com.zy.swagger.service.InterfaceManageService;
import com.zy.swagger.util.HttpRequestUtil;
import com.zy.swagger.util.LoginUserUtil;
import com.zy.swagger.util.PageHelperTool;
import com.zy.swagger.vo.InterfaceManageVO;
import io.swagger.models.HttpMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 接口管理表(表t_interface_manage)服务接口实现类
 *
 * @author ZY
 * @date 2021-04-23 22:37:35
 */
//@DubboService(interfaceClass = InterfaceManageService.class)
@Slf4j
@Service("interfaceManageService")
public class InterfaceManageServiceImpl extends BaseServiceImpl<InterfaceManage, Integer, Object> implements InterfaceManageService {

    /**
     * 注入持久层对象
     */
    @Resource
    private InterfaceManageDao dao;

    @Resource
    private AppManageDao appManageDao;

    @Resource
    private SysUserDao sysUserDao;

    @Resource
    private RequestRecordDao requestRecordDao;

    /**
     * 定义抽象方法getDao获取当前实体Mapper对象
     *
     * @return 当前实体Mapper对象
     */
    @Override
    protected BaseDao<InterfaceManage> getDao() {
        return this.dao;
    }

    /**
     * 新增数据
     *
     * @param dto 参数对象
     * @return 视图对象
     */
    @Override
    public InterfaceManageVO insert(InterfaceManageDTO dto) throws Exception {
        InterfaceManage entity = InterfaceManageConverter.convertFromDTO(dto);
        String headerStr = dto.getHeader();
        Map headers = Maps.newHashMap();
        if (!StringUtils.isEmpty(headerStr)) {
            try {
                headers = JSON.parseObject(headerStr, Map.class);
            } catch (Exception e) {
                log.error("非JSON格式请求头：", e);
                headers.put("Authorization", headerStr);
            }
        }
        entity.setHeader(JSON.toJSONString(headers));
        entity.setCreateTime(new Date());
        InterfaceManage res = super.insertSelective(entity);
        if (res != null) {
            return InterfaceManageConverter.convertToVO(res);
        }
        return null;
    }

    /**
     * 删除对象
     *
     * @param dto 参数对象
     * @return 1:删除成功 其他:删除失败
     */
    @Override
    public Integer delete(CommonIdDTO dto) {
        // 有关联关系最好使用逻辑删除
        InterfaceManage entity = InterfaceManage.builder().id(Integer.parseInt(dto.getId())).delFlag(1).updateTime(new Date()).build();
        return super.updateByPrimaryKeySelective(entity);
    }

    /**
     * 更新对象
     *
     * @param dto 待更新的DTO对象
     * @return 成功返回更新后的VO对象，失败返回null
     */
    @Override
    public InterfaceManageVO update(InterfaceManageDTO dto) {
        InterfaceManage entity = InterfaceManageConverter.convertFromDTO(dto);
        String headerStr = dto.getHeader();
        Map headers = Maps.newHashMap();
        if (!StringUtils.isEmpty(headerStr)) {
            try {
                headers = JSON.parseObject(headerStr, Map.class);
            } catch (Exception e) {
                log.error("非JSON格式请求头：", e);
                headers.put("Authorization", headerStr);
            }
        }
        entity.setHeader(JSON.toJSONString(headers));
        entity.setUpdateTime(new Date());
        int res = super.updateByPrimaryKeySelective(entity);
        if (res == 1) {
            return InterfaceManageConverter.convertToVO(entity);
        }
        return null;
    }

    /**
     * 根据ID查询数据
     *
     * @param dto 主键DTO对象
     * @return 成功返回对应ID的VO对象，失败返回null
     */
    @Override
    public InterfaceManageVO getById(CommonIdDTO dto) {
        InterfaceManage entity = super.getByPrimaryKey(Integer.parseInt(dto.getId()));
        if (entity != null) {
            return InterfaceManageConverter.convertToVO(entity);
        }
        return null;
    }

    /**
     * 根据条件查询数据集合
     *
     * @param dto 查询条件对象
     * @return 满足条件的数据集合
     */
    @Override
    public List<InterfaceManageVO> getList(InterfaceManageDTO dto) {
        Example example = new Example(InterfaceManage.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("delFlag", 0);
        List<InterfaceManage> list = super.selectByExample(example);
        if (!CollectionUtils.isEmpty(list)) {
            List<InterfaceManageVO> retList = new ArrayList<>();
            list.forEach(x -> retList.add(InterfaceManageConverter.convertToVO(x)));
            return retList;
        }
        return new ArrayList<>();
    }

    /**
     * 根据条件查询分页
     *
     * @param dto  查询条件
     * @return 满足条件的分页
     */
    @Override
    public PageInfo<InterfaceManageVO> getPageInfo(InterfaceManageDTO dto) {
        Integer pageNum = dto.getPageNum();
        Integer pageSize = dto.getPageSize();

        Example example = new Example(InterfaceManage.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("delFlag", 0);
        if (dto.getAppId() != null) {
            criteria.andEqualTo("appId", dto.getAppId());
        }
        if (dto.getUserId() != null) {
            criteria.andEqualTo("userId", dto.getUserId());
        }
        if (dto.getStatus() != null) {
            criteria.andEqualTo("status", dto.getStatus());
        }
        if (!StringUtils.isEmpty(dto.getName())) {
            criteria.orLike("name", "%" + dto.getName() + "%");
            criteria.orLike("path", "%" + dto.getName() + "%");
        }

        PageInfo<InterfaceManage> pageInfo = PageHelper.startPage(pageNum, pageSize).setOrderBy("id desc").doSelectPageInfo(() -> super.selectByExample(example));
        if (pageInfo == null || CollectionUtils.isEmpty(pageInfo.getList())) {
            return PageHelperTool.initPageInfoObj(pageNum, 0, pageSize, new PageInfo<>(Lists.newArrayList()));
        }
        List<InterfaceManageVO> retList = new ArrayList<>();
        pageInfo.getList().forEach(x -> {
            InterfaceManageVO vo = InterfaceManageConverter.convertToVO(x);
            vo.setAppName(appManageDao.selectByPrimaryKey(x.getAppId()).getAppName());
            vo.setUserName(sysUserDao.selectByPrimaryKey(x.getUserId()).getName());
            retList.add(vo);
        });
        return PageHelperTool.initPageInfoObj(pageNum, (int) pageInfo.getTotal(), pageSize, new PageInfo<>(retList));
    }

    /**
     * 测试接口是否正常
     *
     * @param dto 请求参数
     * @return 返回 true:成功 false:失败
     */
    @Override
    public Boolean testInterface(InterfaceManageDTO dto) {
        Integer id = dto.getId();
        Integer appId = dto.getAppId();
        String method = dto.getMethod();
        String path = dto.getPath();
        String headerStr = dto.getHeader();
        String paramsStr = dto.getParams();
        String env = dto.getEnv();

        // 获取请求地址
        String requestUrl = getRequestUrl(appId, path, env);

        // 获取请求头
        Map headers = Maps.newHashMap();
        if (!StringUtils.isEmpty(headerStr)) {
            try {
                headers = JSON.parseObject(headerStr, Map.class);
            } catch (Exception e) {
                log.error("非JSON格式请求头：", e);
                headers.put("Authorization", headerStr);
            }
        }

        // 获取请求参数
        Map params = Maps.newHashMap();
        if (!StringUtils.isEmpty(paramsStr)) {
            if (Objects.equals(HttpMethod.GET.name(), method)) {
                // 如果是GET请求，解析可能存在的参数
                params = HttpRequestUtil.toMap(paramsStr);
            } else if (Objects.equals(HttpMethod.POST.name(), method)) {
                // 如果是POST请求，解析可能存在的参数
                params = JSON.parseObject(paramsStr, Map.class);
            } else {
                throw new BaseException(400, "暂不支持该请求类型");
            }
        }
        InterfaceManage interfaceManage = this.dao.selectByPrimaryKey(id);
        log.info("接口测试=> 请求地址：{}，请求头：{}，请求方式：{}， 请求参数：{}", requestUrl, JSON.toJSONString(headers), method, JSON.toJSONString(params));
        try {
            Map result;
            if (Objects.equals(HttpMethod.GET.name(), method)) {
                result = HttpRequestUtil.sendGet(requestUrl, headers, params, Map.class);
            } else if (Objects.equals(HttpMethod.POST.name(), method)) {
                result = HttpRequestUtil.sendPost(requestUrl, headers, params, Map.class);
            } else {
                throw new BaseException(400, "暂不支持该请求类型");
            }
            if (result != null && (Objects.equals(result.get("status"), 200) || Objects.equals(result.get("code"), 200))) {
                if (interfaceManage.getStatus() != 1) {
                    interfaceManage.setStatus(1);
                    this.dao.updateByPrimaryKey(interfaceManage);
                }
                RequestRecord record = RequestRecord.builder()
                        .appId(appId)
                        .interfaceId(id)
                        .requestUrl(requestUrl)
                        .method(method)
                        .header(JSON.toJSONString(headers))
                        .params(Objects.equals(method, HttpMethod.GET.name()) ? paramsStr : JSON.toJSONString(params))
                        .userId(LoginUserUtil.getCurrentUserId())
                        .resp(JSON.toJSONString(result))
                        .status(1)
                        .createTime(new Date())
                        .updateTime(new Date())
                        .build();
                requestRecordDao.insertSelective(record);
                return true;
            } else {
                if (interfaceManage.getStatus() != 0) {
                    interfaceManage.setStatus(0);
                    this.dao.updateByPrimaryKey(interfaceManage);
                }
                RequestRecord record = RequestRecord.builder()
                        .appId(appId)
                        .interfaceId(id)
                        .requestUrl(requestUrl)
                        .method(method)
                        .header(JSON.toJSONString(headers))
                        .params(Objects.equals(method, HttpMethod.GET.name()) ? paramsStr : JSON.toJSONString(params))
                        .userId(LoginUserUtil.getCurrentUserId())
                        .resp(JSON.toJSONString(result))
                        .status(0)
                        .createTime(new Date())
                        .updateTime(new Date())
                        .build();
                requestRecordDao.insertSelective(record);
                return true;
            }
        } catch (Exception e) {
            log.error("接口测试异常：", e);
        }
        if (interfaceManage.getStatus() != 0) {
            interfaceManage.setStatus(0);
            this.dao.updateByPrimaryKey(interfaceManage);
        }
        RequestRecord record = RequestRecord.builder()
                .appId(appId)
                .interfaceId(id)
                .requestUrl(requestUrl)
                .method(method)
                .header(JSON.toJSONString(headers))
                .params(Objects.equals(method, HttpMethod.GET.name()) ? paramsStr : JSON.toJSONString(params))
                .userId(LoginUserUtil.getCurrentUserId())
                .resp("")
                .status(0)
                .createTime(new Date())
                .updateTime(new Date())
                .build();
        requestRecordDao.insertSelective(record);
        return false;
    }

    /**
     * 获取请求URL地址
     *
     * @param appId 应用ID
     * @param path 请求path
     * @param env 环境
     * @return 返回对应环境的请求URL地址
     */
    private String getRequestUrl(Integer appId, String path, String env) {
        String requestUrl = "";
        AppManage app = appManageDao.selectByPrimaryKey(appId);
        if (!StringUtils.isEmpty(app.getSwaggerUrl())) {
            Map<String, String> map = JSON.parseObject(app.getSwaggerUrl(), Map.class);
            if (map.containsKey(env)) {
                String swaggerUrl = map.get(env);
                requestUrl = HttpRequestUtil.getIpPort(swaggerUrl) + path;
            }
        } else {
            String envIp = ProjectConstant.getEnvMap().get(env);
            requestUrl = "http://" + envIp + ":" + app.getPort() + path;
        }
        return requestUrl;
    }


}